package com.example.common.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.common.enums.OrderStatusEnum;
import com.example.common.exception.ServiceException;
import com.example.common.mapper.GoodsSpecMapper;
import com.example.common.mapper.OrderGoodsSnapshotMapper;
import com.example.common.mapper.OrderMapper;
import com.example.common.po.GoodsSpecPO;
import com.example.common.po.OrderPO;
import com.example.common.po.OrderGoodsSnapshotPO;
import com.example.common.service.OrderService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.core.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;
import java.util.Objects;

/**
 *
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderPO>
        implements OrderService {
    @Autowired
    private HttpServletRequest httpServletRequest;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private GoodsSpecMapper goodsSpecMapper;

    @Autowired
    private OrderGoodsSnapshotMapper orderGoodsSnapshotMapper;

    @Resource
    DataSourceTransactionManager dataSourceTransactionManager;

    @Resource
    TransactionDefinition transactionDefinition;

    @Autowired
    private AmqpTemplate rabbitTemplate;

    @Value("${app.order.holdTime}")
    private Integer holdTime; //保留订单时间

    @Value("${app.common.debug}")
    private boolean debug;

    /**
     * 清除订单
     *
     * @param orderId
     * @return
     */
    @Override
    public Integer autoCancel(Integer orderId, Channel channel, Message message) throws IOException {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        OrderPO data = orderMapper.selectOne(
                new QueryWrapper<OrderPO>()
                        .lambda()
                        .eq(OrderPO::getOrderId, orderId)
                        .eq(OrderPO::getOrderStatus, OrderStatusEnum.WAIT_PAY.getKey())
        );
        if (Objects.isNull(data)) {
            log.info("找不到资源:{}", orderId);
            return null;
        }
        // 释放库存
        //开启事务
        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
        try {
            List<OrderGoodsSnapshotPO> orderGoodsSnapshotPOArrayList = orderGoodsSnapshotMapper.selectList(
                    new QueryWrapper<OrderGoodsSnapshotPO>()
                            .lambda()
                            .eq(OrderGoodsSnapshotPO::getOrderId, orderId)
            );
            // 补库存
            orderGoodsSnapshotPOArrayList.forEach(e -> {
                goodsSpecMapper.update(
                        new UpdateWrapper<GoodsSpecPO>()
                                .lambda()
                                .eq(GoodsSpecPO::getSkuCode, e.getSkuCode())
                                .setSql("store_count = store_count+" + e.getQuantity())
                );
            });
            // 更新状态
            Integer result = orderMapper.update(new UpdateWrapper<OrderPO>()
                    .lambda()
                    .eq(OrderPO::getOrderId, orderId)
                    .eq(OrderPO::getOrderStatus, OrderStatusEnum.WAIT_PAY.getKey())
                    .set(OrderPO::getOrderStatus, OrderStatusEnum.CANCEL.getKey())
            );
            // 提交
            dataSourceTransactionManager.commit(transactionStatus);
            log.info("处理过期订单:{}", orderId);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            return result;
        } catch (Exception e) {
            // 回滚
            dataSourceTransactionManager.rollback(transactionStatus);
            // 重试
            if(message.getMessageProperties().getReceivedDelay()==0){
                channel.basicNack(deliveryTag,false, true);
                log.info("处理过期订单失败,重新投递:{}", orderId);
            }else{
                // 重试过了
                log.info("处理过期订单异常:{}", orderId,message);
            }
            throw new ServiceException(e.getMessage(), 106);
        }
    }
}




